#include <boost/asio/detail/socket_ops.hpp>
#include <cstdint>
#include <iostream>
#include <boost/asio.hpp>

const int max_length = 64;
const uint16_t HEAD_LENGTH = sizeof(uint16_t);

int main(void)
{
    try
    {
        boost::asio::io_context io_context;
        boost::asio::ip::address address = boost::asio::ip::address::from_string("127.0.0.1");
        boost::asio::ip::tcp::endpoint endpoint(address, 12345);

        boost::asio::ip::tcp::socket socket(io_context);
        boost::system::error_code error = boost::asio::error::host_not_found;
        socket.connect(endpoint, error);
        if (error)
        {
            std::cerr << "Connect failed: " << error.message() << "\n";
            return -1;
        }

        std::cout << "Enter message: ";
        char request[max_length];
        std::cin.getline(request, max_length);
        uint16_t length = std::strlen(request);
        uint16_t net_length = boost::asio::detail::socket_ops::host_to_network_short(length);
        char send_data[max_length] = { 0 };
        memcpy(send_data, &net_length, HEAD_LENGTH);
        memcpy(send_data + HEAD_LENGTH, request, max_length);
        boost::asio::write(socket, boost::asio::buffer(send_data, length + HEAD_LENGTH));

        char reply_head[HEAD_LENGTH];
        uint16_t reply_length = boost::asio::read(socket,boost::asio::buffer(reply_head, HEAD_LENGTH));
        uint16_t msglen = 0;
        memcpy(&msglen, reply_head, HEAD_LENGTH);
        msglen = boost::asio::detail::socket_ops::network_to_host_short(msglen);

        char msg[max_length] = { 0 };
        size_t  msg_length = boost::asio::read(socket,boost::asio::buffer(msg, msglen));
        
        std::cout << "Reply is: ";
        std::cout.write(msg, msglen) << std::endl;
        std::cout << "Reply len is " << msglen;
        std::cout << "\n";
    }
    catch (const std::exception& e)
    {
        std::cerr << "Exception: " << e.what() << "\n";
        return -2;
    }

    return 0;
}